/**
 * 条件类型中 使用infer关键字 进行类型推断
 */
type GetReturnType<T extends (...args: any[]) => any> = T extends (
  ...args: any[]
) => infer R
  ? R
  : never;
type A = GetReturnType<() => void>;
type B = GetReturnType<(n: number) => number>;

// type IsString<T> = T extends infer R ? R : never;
// type C = IsString<"你好">;
// type D = IsString<123>;

// type LiteralToPrimitive<T> = T extends number
//   ? number
//   : T extends bigint
//   ? bigint
//   : T extends string
//   ? string
//   : never;
// function universalAdd<T extends number | bigint | string>(
//   x: T,
//   y: T
// ): LiteralToPrimitive<T> {
//   return x + (y as any);
// }

// const asd = universalAdd(111n, 22n);

/**
 * 条件类型判断函数
 */
type Func = (...args: any[]) => any;

// type FunctionConditionType<T extends Func> = T extends (
//   ...args: any[]
// ) => string
//   ? "a string return func!"
//   : "a non-string return func";
// type StringResult = FunctionConditionType<() => string>;
// type NonStringResult = FunctionConditionType<() => number>;

/**
 * 条件类型 + infer 判断函数返回值
 */
// type FunctionReturnType<T extends Func> = T extends (...args: any[]) => infer R
//   ? R
//   : never;

// type StringResult = FunctionReturnType<() => number | string>; // string | number

/**
 * 条件类型 + infer 操作数组交换
 */
// type Swap<T extends any[]> = T extends [infer A, infer B] ? [B, A] : T;
// type SwapResult1 = Swap<[1, 2]>; // [2,1]
// type SwapResult2 = Swap<[1, 2, 3]>; // [1,2,3]
type ExtractStartAndEnd<T extends any[]> = T extends [
  infer Start,
  ...any[],
  infer End
]
  ? [Start, End]
  : T;
type SwapStartAndEnd<T extends any[]> = T extends [
  infer Start,
  ...infer Left,
  infer End
]
  ? [End, ...Left, Start]
  : T;
// 调换开头两个
type SwapFirstTwo<T extends any[]> = T extends [
  infer Start,
  infer End,
  ...infer Left
]
  ? [End, Start, ...Left]
  : T;
// 结构类型层面的转换
type ArrayItemType<T extends any[]> = T extends Array<infer ElementType>
  ? ElementType
  : never;
type ArrayItemTypResult1 = ArrayItemType<[string, number]>; // 这里的[string, number] 等价于 (string | number)[] 从而触发分布式特性，返回string | number;

// 作为接口
type PropType<T, K extends keyof T> = T extends { [Key in K]: infer R }
  ? R
  : never;
type PropTypeResult1 = PropType<{ name: string }, "name">; // string;
type PropTypeResult2 = PropType<{ name: string; age: number }, "age" | "name">; // string | number

// 反转键名和键值
type ReverseKeyValue<T extends Record<string, unknown>> = T extends Record<
  infer K,
  infer V
>
  ? Record<V & string, K> // 使用 & string 来保证键名是string类型，避免报错
  : never;
type ReverseKeyValueResult1 = ReverseKeyValue<{ key: "value" }>;

// 处理Promise
type PromiseValue<T> = T extends Promise<infer V> ? V : T;

/**
 * 手写Merge
 */
type MyMerge<T extends Record<any, any>, U extends Record<any, any>> = {
  [K in keyof T | keyof U]: K extends keyof U ? U[K] : T[K];
};

type ASd = MyMerge<{ name: string }, { age: number; name: number }>;

export {};
